<?php
namespace Tbf\Bundle\CronBundle\Entity;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Tbf\Component\DateTime\DateSequence\DateSequenceInterface;
use Tbf\Bundle\TaskManageBundle\TaskInterface;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="\Tbf\Bundle\CronBundle\Entity\CronRepository")
 * @ORM\Table(name="tbf_cron",indexes={@ORM\Index(name="next_time", columns={"next_time"})} )
 * @ORM\HasLifecycleCallbacks
 */
class Cron
{
    /**
     * @ORM\Id
     * @ORM\Column()
     * @ORM\GeneratedValue(strategy="UUID")
     */
    protected $id;

    /**
     * 用于表示如何获取下一次的执行时间
     * @var DateSequenceInterface
     * @ORM\Column(type="object")
     * */
    protected $date_sequence;

    /**
     * 一旦生成不可修改
     * @var TaskInterface
     * @ORM\Column(type="object")
     */
    protected $task;

    /**
     * 下一次执行时间,建立索引以便数据库查找
     * @var \DateTime
     * @ORM\Column(type="datetime")
     */
    protected $next_time;

    /**
     * update之前,更新里面几个对象的reference
     * @ORM\PrePersist
     */
    public function onPrePersist()
    {
        $this->date_sequence = clone $this->date_sequence;
        if ($this->task instanceof ContainerAware) {
            $ref = new \ReflectionObject($this->task);
            $pro = $ref->getProperty('container');
            $pro->setAccessible(true);
            $pro->setValue($this->task,null);
        }
        $this->task = clone $this->task;
        $this->next_time = clone $this->next_time;
    }
    /**
     * @param DateSequenceInterface $date_sequence
     * @param TaskInterface         $task
     */
    public function __construct(DateSequenceInterface $date_sequence,TaskInterface $task)
    {
        $this->date_sequence = $date_sequence;
        $this->task = $task;
        $this->next_time = $this->date_sequence->current();
    }

    public function run(ContainerInterface $container)
    {
        if ($this->task instanceof ContainerAware) {
            $this->task->setContainer($container);
        }
        $this->task->run();
    }

    /**
     * 修改这个cron的内部状态,使其移动到下一个执行时间
     */
    public function moveTimeNext(\DateTime $now_time){
        $this->date_sequence->next();
        $this->date_sequence->setTimeAfter($now_time);
        $this->next_time = $this->date_sequence->current();
    }
    public function isValid()
    {
        return $this->date_sequence->valid();
    }
    public function getNextTime()
    {
        return $this->next_time;
    }
    public function getTask()
    {
        return $this->task;
    }
    public function getId()
    {
        return $this->id;
    }
}
